﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufButtonEx.h"
#include "GnufQtItem.h"
#include <QLabel>
#include <QPushButton>

namespace gnuf {
    class ButtonAppearanceSetting;
    class QtButtonExImpl;
    class QtButtonEx;

    class QtButtonText : public QLabel
    {
    public:
        QtButtonText(QWidget* parent = nullptr);
        virtual ~QtButtonText() {};

    public:
        void setText(const QString&);
        void setMaxTextWidth(int);
        inline int maxTextWidth() const { return m_maxTextWidth; }
        inline bool elided() const { return m_isElided; }

    protected:
        virtual void resizeEvent(QResizeEvent*);

    private:
        QString m_text;
        int m_maxTextWidth;
        bool m_isElided = false;
    };

    class QtButtonIcon : public QLabel
    {
    public:
        QtButtonIcon(QWidget* parent = nullptr);
        virtual ~QtButtonIcon() {};
    protected:
        virtual void paintEvent(QPaintEvent* pEvt) override;
    };

    class QtBadgeLabel : public QLabel
    {
    public:
        QtBadgeLabel(const BadgeAppearanceSetting*,QWidget* parent);
        virtual ~QtBadgeLabel() {};
    public:
        const BadgeAppearanceSetting* badgeSetting() const { return m_wpBadgeSetting.Get(); }
        void setBadgeSetting(const BadgeAppearanceSetting* setting) { m_wpBadgeSetting = setting; }

        const std::wstring& badgeText() const { return m_text; }
        void setBadgeText(const std::wstring& text) { m_text = text; }
        void setBadgeSize();
        const QPoint calculateBadgePosition();
    protected:
        virtual void paintEvent(QPaintEvent *) override;

    private:
        gcmp::WeakPtr<BadgeAppearanceSetting> m_wpBadgeSetting;
        std::wstring m_text;
    };

    class QtButtonEx : public QtItemWith<QPushButton, ButtonEx, QWidget*>
    {
        Q_OBJECT
        Q_PROPERTY(bool ShouldIgnoreRecord READ ShouldIgnoreRecord)
    public:
        virtual ~QtButtonEx() {
            disconnect(this); // no longer be a receiver
            disconnectFromItem();
        }
        virtual void refresh(QtItem::EWhatDirty) override;
        bool ShouldIgnoreRecord();
        void onTableRowSelectionChanged(bool);
        int expectedHeight(int * pMaxHeightOfButtonCaption = nullptr) const;

        static int heightOf(const QLabel & qtLabel);

    public:
        inline std::wstring text() const {
            return m_textLabel == nullptr ? L"" : m_textLabel->text().toStdWString();
        }

        inline Direction direction() const { return m_direction; }
        inline bool elided() const { return m_textLabel->elided(); }

        void refreshAll();

        QLabel* iconLabel() const { return m_iconLabel; }
        QLabel* textLabel() const { return m_textLabel; }
        QtBadgeLabel* badgeLabel() const { return m_badgeLabel; }
        const ButtonAppearanceSetting* setting() const { return m_setting.Get(); }

        // Be very careful when you decide to call this method.
        // The pSetting should have longer life span than this buttonEx.
        void setSetting(const ButtonAppearanceSetting* pSetting) { m_setting = pSetting; }
    private slots:
        void onClicked(bool);
        void onToggled(bool);

    protected:
        virtual void enterEvent(QEvent *) override;
        virtual void leaveEvent(QEvent *) override;
        virtual void paintEvent(QPaintEvent *) override;
        virtual void mousePressEvent(QMouseEvent *) override;
        virtual void mouseReleaseEvent(QMouseEvent *) override;
        virtual bool event(QEvent *) override;
        virtual void hideEvent(QHideEvent *) override;

    protected:
        explicit QtButtonEx(const char*, ButtonEx*, const ButtonAppearanceSetting*, Direction, QWidget* parent);


    protected:
        virtual void initialize();
        virtual void setInfo(const Info*);
        virtual void setText(const std::wstring& text);
        virtual void setTooltip(const std::wstring& tooltip);
        virtual void refreshIcon(const Info*);
        virtual void updateIcon();
        virtual void setStyle();
        virtual void setSelection(bool);

    private:
        virtual void updateStyle();
        virtual void normalStyleSheet();
        virtual void hoveredStyleSheet();
        virtual void pressedStyleSheet();
        virtual void selectedStyleSheet();
        virtual void disabledStyleSheet();
        // update style is selected on table
        void adjustStyleSheet(bool selected);
        void setOpacityEffect(bool bOpacity);
    protected:
        enum class Mode
        {
            Normal,
            Hover,
            Pressed,
            Selected,
            Disabled
        } m_mode;

    protected:
        QtButtonText* m_textLabel;

    private:
        gcmp::OwnerPtr< QtButtonExImpl > m_opImpl;
        QIcon m_icon;
        QtButtonIcon* m_iconLabel = nullptr;
        gcmp::WeakPtr<ButtonAppearanceSetting> m_setting;
        Direction m_direction;
        bool m_pressed;
        bool m_bSelected;
        QtBadgeLabel* m_badgeLabel;
        QString  m_oldStyleSheet;
    };
}
